const socket_mongo = require('./socket_mongo')
const jwt = require('jsonwebtoken')
const config = require('../config/jwt_secret/secert')
module.exports = (io) => {
    var users = {}
    var num = 0
    var scanUsers = {}
    io.on("connection", (socket) => {
        /**
         * 二维码状态
         * qrcode_status:
         *      0 => 未扫
         *      1 => 已扫，未确认
         *      2 => 已确认
         *      3 => 二维码过期
         */
        // 创建二维码（桌面端）
        socket.on('create_qrcode', ({ uuid, socketId }) => {
            socket.name_uuid = uuid
            scanUsers[uuid] = socket.id
            socket.emit('qrcode_status', {
                qrcode_status: 0,
                uuid,
                socketId
            })
        })

        // 二维码扫描成功（移动端）
        socket.on('scan_qrcode', ({ _id, token, code_info }) => {
            // 解code_info二维码信息（二维码携带桌面端uuid）
            try {
                let decode = jwt.verify(code_info, config.jwtSecret)
                let uuid = decode.uuid
                // 桌面端
                socket.to(scanUsers[uuid]).emit('qrcode_status', {
                    qrcode_status: 1,
                    uuid,
                    socketId: socket.id
                })
                // 移动端
                socket.emit('qrcode_status', {
                    qrcode_status: 1,
                    uuid,
                    socketId: socket.id
                })
            } catch (error) {
                // 二维码过期
                // 桌面端
                socket.to(scanUsers[uuid]).emit('qrcode_status', {
                    qrcode_status: 3,
                    uuid,
                    socketId: socket.id
                })
                // 移动端
                socket.emit('qrcode_status', {
                    qrcode_status: 3,
                    uuid,
                    socketId: socket.id
                })
            }
        })

        // 移动端确认登陆
        socket.on('confirm_qrcode', ({ userInfo, code_info, uuid }) => {
            try {
                jwt.verify(code_info, config.jwtSecret)
                // 移动端
                socket.emit('qrcode_status', {
                    qrcode_status: 2,
                    uuid,
                    socketId: socket.id
                })
                // 桌面端
                socket.to(scanUsers[uuid]).emit('qrcode_status', {
                    qrcode_status: 2,
                    uuid,
                    socketId: socket.id,
                    userInfo
                })
            } catch (error) {
                // 移动端
                socket.emit('qrcode_status', {
                    qrcode_status: 3,
                    uuid,
                    socketId: socket.id
                })
            }
            if (scanUsers.hasOwnProperty(uuid)) {
                delete scanUsers[uuid]
            }
        })

        // 用户登录
        socket.on('login', async (userId) => {
            // socket.name => 用户id
            socket.name = userId
            users[userId] = socket.id
            socket.emit('login', socket.id)
            num += 1
            // 判断是否有没退出的通话记录
            await socket_mongo.userCloseTelephone({ userId })
            console.log('==============进入=============');
            // console.log('userId', userId);
            // console.log('用户连接', socket.id);
            console.log('在线人数', num);
            console.log('===============================');
        })

        // 一对一消息(private_chat)
        socket.on('private_chat', async (dataMsg, uId, fId) => {
            // fromId(发送者) => uId(userId)  toId(接收者) => fId(friendId)
            try {
                // 将消息存数据库
                await socket_mongo.savePrivateChatMsg({ dataMsg, uId, fId })
                let data = {
                    userId: dataMsg.userId,
                    msgType: dataMsg.msgType,  // msgType 消息类型（0:文字（包括表情包），1:图片）
                    message: dataMsg.message,
                    time: new Date(),
                    fromId: uId,
                    toId: fId
                }
                socket.to(users[fId]).emit('private_chat', data)
                // 未读好友消息
                socket.to(users[fId]).emit('unread_message', uId)
            } catch (error) {
            }
        })

        // 进入群聊(join_group)
        socket.on('join_group', (gId) => {
            socket.join(gId)
        })

        // 群聊(group_chat)
        socket.on('group_chat', async (dataMsg, uId, gId) => {
            // fromId(发送者) => uId(userId)  toId(接收者) => gId(groupId)
            try {
                // 将消息存数据库
                let saveInfo = await socket_mongo.saveGroupChatMsg({ dataMsg, uId, gId })
                let messageId = saveInfo._id.toString() // 消息id
                // 将用户消息设置为未读  参数: 消息id 群id 发消息人的id
                await socket_mongo.groupMessageUnRead(messageId, gId, uId) // 不包含发送者
                // 查询群聊信息
                let info = await socket_mongo.findGroupInfo({ groupId: gId })
                let data = {
                    userId: dataMsg.userId, // 发消息好友信息
                    groupInfo: {
                        _id: info._id,
                        groupName: info.groupName,
                        imgUrl: info.imgUrl
                    }, // 群聊信息
                    msgType: dataMsg.msgType,  // msgType 消息类型（0:文字（包括表情包），1:图片）
                    message: dataMsg.message,
                    time: new Date(),
                    fromId: uId,
                    toId: gId
                }
                socket.to(gId).emit('group_chat', data)
                socket.to(gId).emit('unread_message', gId)
            } catch (error) {
            }
        })

        // 初始化申请消息通知
        socket.on('init_apply_notice', async (toId) => {
            // toId 接收方id
            let friendNoticeNum = await socket_mongo.friendNoticeNum(toId)
            let groupNoticeNum = await socket_mongo.groupNoticeNum(toId)
            socket.emit('init_apply_notice', { friendNoticeNum, groupNoticeNum })
        })

        // 好友、群申请通知
        socket.on('apply_notice', async (toId) => {
            // 好友申请消息
            let friendNoticeNum = await socket_mongo.friendNoticeNum(toId)
            // 入群申请消息
            let groupNoticeNum = await socket_mongo.groupNoticeNum(toId)
            socket.to(users[toId]).emit('apply_notice', { friendNoticeNum, groupNoticeNum })
        })

        // 同意好友/群申请
        socket.on('agree_apply', async (toId, id) => {
            // toId 接收方id  id 好友id/群id(群聊申请通过才需要)
            socket.to(users[toId]).emit('agree_apply', id)
        })

        // 群主同意入群申请后, 申请方加入群聊房间
        socket.on('agree_apply_join_group', (gId) => {
            socket.join(gId)
        })

        // 退出群聊, 需要离开房间
        socket.on('leave_group', (gId) => {
            socket.leave(gId)
            socket.emit('leave_group', gId)
        })

        // 解散群聊
        socket.on('del_group', (gId) => {
            socket.to(gId).emit('del_group', gId)
        })

        // 用户被踢出群聊(由被踢出的那个用户发送socket)
        socket.on('notice_out_group', (userId, groupId) => {
            socket.to(users[userId]).emit('notice_out_group', groupId)
        })

        // 删除好友
        socket.on('del_friend', (userId, toId) => {
            socket.to(users[toId]).emit('del_friend', userId)
        })

        // 视频、语音通话消息提示
        socket.on('notice_telephone', (data) => {
            // data数据
            /**
             *  let data = {
                    fId: xxx, // 用户id
                    toId: xxx, // urlid（好友id/群id）
                    chatType, // 聊天类型(群聊group/私聊friend)
                    type // 通话类型
                }
             */
            let toId = data.toId
            if (data.chatType === 'friend') {
                socket.to(users[toId]).emit('notice_telephone', data)
            } else {
                socket.to(toId).emit('notice_telephone', data)
            }
        })

        // 记录正在通话的用户
        socket.on('user_jion_telephone', async (data) => {
            let joinUsers = await socket_mongo.userJoinTelephone(data)
            Object.assign(data, { users: joinUsers })
            if (data.type === 'screen') return
            if (data.chatType === 'group' && data.type !== 'screen') {
                // 加入房间
                socket.join('group_' + data.toId)
            }
            socket.to(users[data.userId]).emit('user_jion_telephone', data)
        })

        // 新加入的用户通知其他用户（用于界面展示）
        socket.on('add_group_telephone', async (data) => {
            if (data.type === 'screen') return
            let telephoneUsers = await socket_mongo.userJoinTelephone(data)
            telephoneUsers.filter(user => user.userId.toString() !== data.userId).forEach(item => {
                let uId = item.userId.toString()
                socket.to(users[uId]).emit('add_group_telephone', data)
            })
        })

        // 通知发起方, 接收方已同意加入通话
        socket.on('accept_telephone', (data) => {
            /**
             *  let data = {
                    acceptId: xxx, // 同意方id
                    fId: xxx, // 发起方id
                    toId: xxx, // urlid（好友id/群id）
                    chatType, // 聊天类型(群聊group/私聊friend)
                    type // 通话类型
                }
             * 
             */
            // 发起方id
            let fId = data.fId
            // 通知发起方, 接收方已同意加入通话
            socket.to(users[fId]).emit('accept_telephone', data)
        })

        // 同意方接收发起方的offer
        socket.on('send_offer', (params) => {
            /**
             * params = {
                    offer,
                    fId, // 发起方id
                    acceptId, // 同意方id
                    type, // 通话类型(screen/voice/video)
                    chatType // 聊天类型(私聊/群聊)
                }
             */
            socket.to(users[params.acceptId]).emit('send_offer', params)
        })

        // 发起方接收同意方的answer
        socket.on('send_answer', (params) => {
            socket.to(users[params.fId]).emit('send_answer', params)
        })

        // 发起方向同意方交换candidate信息
        socket.on('send_candidate', (candidateData) => {
            if (candidateData.userType === candidateData.fId) {
                // 发起方向接收方发送candidate信息
                socket.to(users[candidateData.acceptId]).emit('send_candidate', candidateData)
            } else {
                // 解释发向发起方发送candidate信息
                socket.to(users[candidateData.fId]).emit('send_candidate', candidateData)
            }
        })

        // 屏幕共享(加入房间)
        socket.on('join_telephone_room', (roomId) => {
            // 加入房间
            socket.join(roomId)
        })

        // 屏幕共享通话, 会议消息
        socket.on('telephone_message', (msgData, otherData) => {
            socket.to(otherData.toId).emit('telephone_message', msgData)
        })

        // 结束通话
        socket.on('close_telephone', async (data) => {
            /**
             *  let data = {
                    userId: xxx, // 用户id
                    toId: xxx, // 群id/好友id
                    chatType: xxx
             *  }
             */
            try {
                await socket_mongo.userCloseTelephone(data)
                if (data.type === 'screen') return
                if (data.chatType === 'group') {
                    // 群聊: 告诉其他成员: 有用户退出
                    socket.to('group_' + data.toId).emit('close_telephone', data)
                } else {
                    // 私聊: 结束聊天
                    let other = await socket_mongo.getTelephoneOtherUser(data)
                    other.forEach(item => {
                        let uId = item.userId.toString()
                        socket.to(users[uId]).emit('close_telephone', data)
                    })
                }
            } catch (error) {
                console.log(error);
            }
        })

        // 退出登陆
        socket.on('logout', async (userId) => {
            if (users.hasOwnProperty(socket.name)) {
                delete users[socket.name]
                num -= 1
                // 退出
                await socket_mongo.userCloseTelephone({ userId })
                console.log('=============离开============');
                console.log(socket.id, socket.name, '用户关闭连接')
                console.log('在线人数', num);
                console.log('============================');
            }
        })

        socket.on('disconnect', async function () {
            if (users.hasOwnProperty(socket.name)) {
                delete users[socket.name]
                num -= 1
                // 退出
                await socket_mongo.userCloseTelephone({ userId: socket.name })
                console.log('=============离开============');
                console.log(socket.id, socket.name, '用户关闭连接')
                console.log('在线人数', num);
                console.log('============================');
            }
        })
    })
}